﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using System.Web.UI;

namespace DeployWebLibUtils
{
    public static class Extensions
    {
        public static string RenderControl(this Control control)
        {
            StringBuilder sb = new StringBuilder();
            using (StringWriter sw = new StringWriter(sb))
            {
                using (HtmlTextWriter textWriter = new HtmlTextWriter(sw))
                {
                    control.RenderControl(textWriter);
                }
            }

            return sb.ToString();
        }

        /// <summary>
        /// Extension method to detect if specified control is invoking callback action to server
        /// </summary>
        /// <param name="control"></param>
        /// <returns></returns>
        public static bool IsInvokingCallback(this Control control)
        {
            if (control != null)
            {
                return string.Compare(control.UniqueID, control.Page.Request.Params["__CALLBACKID"], true) == 0;
            }

            return false;
        }

        public static Type GetWebEmbeddControlType(this Type userControl)
        {
            EmbeddTypeInfo resultTypeName = userControl.GetEmbeddedControlTypeInfo();
            Type resultType = Type.GetType(resultTypeName.FullTypeName, false);
            return resultType;
        }

        public static EmbeddTypeInfo GetEmbeddedControlTypeInfo(this Type userControl)
        {
            EmbeddTypeInfo result = new EmbeddTypeInfo();

            string assemblyName = userControl.Assembly.GetName().Name;
            string controlNamespace = userControl.Namespace;

            string folderPart = string.Empty;
            if (controlNamespace.StartsWith(assemblyName))
            {
                folderPart = controlNamespace.Replace(assemblyName, "");
            }

            if (!string.IsNullOrEmpty(folderPart) && folderPart.StartsWith("."))
            {
                folderPart = folderPart.Remove(0, 1).Replace(".", "_").ToLowerInvariant();
            }
            
            string extension = "";
//            bool controlIsPage = userControl.BaseType == typeof(Page);
//            bool controlIsUserControl = userControl.BaseType == typeof(UserControl);
//            bool isMasterPage = userControl.BaseType == typeof(MasterPage);
            bool controlIsPage = userControl.IsSubclassOf(typeof (Page));
            bool controlIsUserControl = userControl.IsSubclassOf(typeof (UserControl));
            bool isMasterPage = userControl.IsSubclassOf(typeof (MasterPage));

            if (controlIsPage)
            {
                extension = "aspx";
            }
            else if (controlIsUserControl)
            {
                extension = "ascx";
            }
            else if (isMasterPage)
            {
                extension = "master";
            }

            string _partName = string.Format("ASP.{0}{1}_{2},",
                string.IsNullOrEmpty(folderPart) ? string.Empty : folderPart + "_",
                userControl.Name.ToLowerInvariant(), extension);

            result.FullTypeName = _partName + userControl.Assembly.FullName;
            result.TypeName = _partName + userControl.Assembly.GetName().Name;

            // {0} - assembly full name
            // {1} - control type name
//            string embeddResourceToken = string.Format("@@{0}@{1}_{2}.{3}",
//                userControl.Assembly.GetName().Name,
//                //ConvertTo64S(userControl.Assembly.FullName),
//                controlNamespace.Replace(".", "_"),
//                userControl.Name,
//                isMasterPage ? "Master" : extension);

            string[] assItems = userControl.Assembly.FullName.Split(',');

            AssemblyName assName = userControl.Assembly.GetName();
            string embeddResourceToken = string.Format("@@{0}/{1}/{2}/{3}/{4}_{5}.{6}",
                assName.Name,                          // assembly name
                ParseValues(assItems[1]).Value,        // version
                ParseValues(assItems[2]).Value,        // culture
                ParseValues(assItems[3]).Value,        // public key token
                controlNamespace.Replace(".", "_"),    // namespace
                userControl.Name,                      // control name
                isMasterPage ? "Master" : extension);  // control extension

            result.EmbeddResourceToken = embeddResourceToken;

            return result;
        }

        private static KeyValuePair<string, string> ParseValues(string item)
        {
            string[] args = item.Split('=');
            return new KeyValuePair<string, string>(args[0], args[1]);
        }

        public static string GetWebEmbeddControlFullTypeName(this Type userControl)
        {
            Type embeddControlType = userControl.GetWebEmbeddControlType();
            return embeddControlType != null ? embeddControlType.AssemblyQualifiedName : string.Empty;
        }

        public static string ConvertTo64S(string s)
        {
            string res = string.Empty;
            if ((s != null) && (s != string.Empty))
            {
                byte[] bytes = Encoding.UTF8.GetBytes(s);
                res = Convert.ToBase64String(bytes);
            }

            return res;
        }

        public static string ConvertFrom64S(string s)
        {
            string res = string.Empty;
            if (s != null && s != string.Empty)
            {
                byte[] bytes = Convert.FromBase64String(s);
                res = Encoding.UTF8.GetString(bytes);
            }

            return res;
        }
    }

    public struct EmbeddTypeInfo
    {
        public string FullTypeName { get; set; }
        public string TypeName { get; set; }
        public string EmbeddResourceToken { get; set; }
    }
}
